package weixin.ctrl;
/**  
 * @Title WxInterActiveController.java
 * @date 2016年1月15日 上午11:51:59
 * @Copyright (c) 2016, unibroad.com Inc. All rights reserved.
 */

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang.StringUtils;

import base.ctrl.BaseController;
import base.jfinal.anatation.RouteBind;
import base.util.PropertiesContent;
import mt.Const;

/**
 * @Description 微信平台交互接口
 * @Class com.unibroad.touchus.user.center.webapi.client.controller. WxInterActiveController
 * @author suan@unibroad.com
 * @version V1.0
 */
@RouteBind(path = "wx")
public class WxInterActiveCtrl extends BaseController {

    /**
     * 微信首次接入验证
     * 
     * @param request
     * @param response
     */
    public void checkServer() {
        String echostr = getRequest().getParameter("echostr");
        String signature = getRequest().getParameter("signature");
        String nonce = getRequest().getParameter("nonce");
        String timestamp = getRequest().getParameter("timestamp");
        if (checkSignature(signature, timestamp, nonce)) {
            log.debug("首次接入验证,随机串:　" + echostr);
            try {
                renderText(echostr != null ? echostr : "");
            } catch (Exception e) {
                log.error("微信调用处理异常", e);
            }
        } else {
            renderNull();
        }
    }

    /**
     * 微信消息或事件统一的回调接口,5s内返回,否则会重试,最多三次
     * 
     * @param request
     * @param response
     */
    public void msgpoint() {

        final HttpServletRequest request = this.getRequest();

        try {

            final InputStream in = request.getInputStream();
            final int length = request.getContentLength();

            // 微信加密签名
            final String signature = request.getParameter("signature");
            final String msgSignature = request.getParameter("msg_signature");

            // 时间戳
            final String timestamp = request.getParameter("timestamp");

            // 随机数
            final String nonce = request.getParameter("nonce");

            // 加密类型，suan TODO 暂时明文
            final String encrypt_type = request.getParameter("encrypt_type");

            new WxReqCheckTask(in, length, signature, msgSignature, timestamp, nonce, encrypt_type).run();

            renderText(""); // 收到,立刻 返回,wx 不处理内容

        } catch (IOException e) {
            log.error("weixin push return exception", e);
            renderNull();
        }
    }

    @SuppressWarnings("unused")
    private class WxReqCheckTask implements Runnable {

        InputStream in = null;

        int length;

        // 微信加密签名
        String signature, msgSignature, timestamp, nonce, encrypt_type;

        /**
         * Creates a new instance of WxReqCheckTask.
         *
         * @param in
         * @param length
         * @param signature
         * @param msgSignature
         * @param timestamp
         * @param nonce
         * @param encrypt_type
         */
        private WxReqCheckTask(InputStream in, int length, String signature, String msgSignature,
                String timestamp, String nonce, String encrypt_type) {
            super();
            this.in = in;
            this.length = length;
            this.signature = signature;
            this.msgSignature = msgSignature;
            this.timestamp = timestamp;
            this.nonce = nonce;
            this.encrypt_type = encrypt_type;
        }

        /*
         * (non-Javadoc)
         * @see java.lang.Runnable#run()
         */
        @Override
        public void run() {
            // 消息全加密形式,故调用签名不再校验
            // if (!checkSignature(request)) {
            // log.warn("微信调用签名验证失败,URL：" + request.getRequestURI());
            // return;
            // }
            // try {
            // byte[] buf = new byte[length];
            // in.read(buf, 0, length);
            // String content = new String(buf, "UTF-8");
            // content = WXBizMsgCryptUtil.decryptMsg(msgSignature, timestamp,
            // nonce, encrypt_type, content);
            //
            // WeixinPushEvent event = new WeixinPushEvent(content);
            // event.setEncrypt_type(encrypt_type);
            // event.setMsgSignature(msgSignature);
            // event.setNonce(nonce);
            // event.setTimestampStr(timestamp);
            // webAppCtx.publishEvent(event);
            // log.info("weixin push msg {}", content);
            // } catch (IOException e) {
            // log.error("微信调用处理异常", e);
            // }
        }

    }

    /**
     * 微信调用验证,校验确是是来源于微信的调用
     * 
     * @param request
     * @return
     */
    private boolean checkSignature(String signature, String timestamp, String nonce) {

        if (StringUtils.isEmpty(signature) || StringUtils.isEmpty(timestamp) || StringUtils.isEmpty(nonce)) {
            log.warn("微信调用签名验证失败,参数不正确!");
            return false;
        }

        List<String> secureParams = new ArrayList<String>();
        secureParams.add(PropertiesContent.get(Const.WEIXIN_APP_DEV_TOKEN));
        secureParams.add(timestamp);
        secureParams.add(nonce);

        // 1. 将token、timestamp、nonce三个参数进行字典序排序
        Collections.sort(secureParams, new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
                return o1.compareTo(o2);
            }
        });

        // 2. 将三个参数字符串拼接成一个字符串进行sha1加密
        String a = secureParams.get(0) + secureParams.get(1) + secureParams.get(2);
        String temp = DigestUtils.sha1Hex(a);

        boolean matched = StringUtils.equalsIgnoreCase(signature, temp);

        // timestamp=1464765903 echostr=262189871187025375 nonce=783811041
        // signature=bacea2c2d819a1553da440a53d5bbcc58ba25ed4

        log.info("微信调用签名验证" + (matched ? "成功" : "失败"));

        return matched;
    }

}
